package com.miaostars.apakey.utils;

import org.bukkit.entity.Player;
import org.bukkit.util.Vector;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

public class PlayerData {
    
    private static final ConcurrentHashMap<UUID, PlayerData> playerDataMap = new ConcurrentHashMap<>();
    
    private final UUID playerId;
    private Vector lastLocation;
    private long lastGroundTime;
    
    // Violation counters
    private int flyViolations;
    private int noFallViolations;
    private int killAuraViolations;
    private int reachViolations;
    private int inventoryViolations;
    private int highJumpViolations;
    private int speedViolations;
    private int autoClickViolations;
    
    // Click data for CPS checks
    private final List<Long> clicks = new CopyOnWriteArrayList<>();
    
    // XRay detection data
    private final List<Integer> xrayValues = new ArrayList<>();
    private final List<Long> xrayTimestamps = new ArrayList<>();
    
    private PlayerData(UUID playerId) {
        this.playerId = playerId;
        this.lastGroundTime = System.currentTimeMillis();
        this.flyViolations = 0;
        this.noFallViolations = 0;
        this.killAuraViolations = 0;
        this.reachViolations = 0;
        this.inventoryViolations = 0;
        this.highJumpViolations = 0;
        this.speedViolations = 0;
        this.autoClickViolations = 0;
    }
    
    public static PlayerData get(Player player) {
        return playerDataMap.computeIfAbsent(player.getUniqueId(), PlayerData::new);
    }
    
    public static void remove(Player player) {
        playerDataMap.remove(player.getUniqueId());
    }
    
    // Getters and Setters
    public Vector getLastLocation() {
        return lastLocation;
    }
    
    public void setLastLocation(Vector lastLocation) {
        this.lastLocation = lastLocation;
    }
    
    public long getLastGroundTime() {
        return lastGroundTime;
    }
    
    public void setLastGroundTime(long lastGroundTime) {
        this.lastGroundTime = lastGroundTime;
    }
    
    public int getFlyViolations() {
        return flyViolations;
    }
    
    public void incrementFlyViolations() {
        this.flyViolations++;
    }
    
    public void decrementFlyViolations() {
        this.flyViolations = Math.max(0, this.flyViolations - 1);
    }
    
    public void resetFlyViolations() {
        this.flyViolations = 0;
    }
    
    public int getNoFallViolations() {
        return noFallViolations;
    }
    
    public void incrementNoFallViolations() {
        this.noFallViolations++;
    }
    
    public void decrementNoFallViolations() {
        this.noFallViolations = Math.max(0, this.noFallViolations - 1);
    }
    
    public void resetNoFallViolations() {
        this.noFallViolations = 0;
    }
    
    public int getKillAuraViolations() {
        return killAuraViolations;
    }
    
    public void incrementKillAuraViolations() {
        this.killAuraViolations++;
    }
    
    public void decrementKillAuraViolations() {
        this.killAuraViolations = Math.max(0, this.killAuraViolations - 1);
    }
    
    public void resetKillAuraViolations() {
        this.killAuraViolations = 0;
    }
    
    public int getReachViolations() {
        return reachViolations;
    }
    
    public void incrementReachViolations() {
        this.reachViolations++;
    }
    
    public void decrementReachViolations() {
        this.reachViolations = Math.max(0, this.reachViolations - 1);
    }
    
    public void resetReachViolations() {
        this.reachViolations = 0;
    }
    
    public int getInventoryViolations() {
        return inventoryViolations;
    }
    
    public void incrementInventoryViolations() {
        this.inventoryViolations++;
    }
    
    public void decrementInventoryViolations() {
        this.inventoryViolations = Math.max(0, this.inventoryViolations - 1);
    }
    
    public void resetInventoryViolations() {
        this.inventoryViolations = 0;
    }
    
    public int getHighJumpViolations() {
        return highJumpViolations;
    }
    
    public void incrementHighJumpViolations() {
        this.highJumpViolations++;
    }
    
    public void decrementHighJumpViolations() {
        this.highJumpViolations = Math.max(0, this.highJumpViolations - 1);
    }
    
    public void resetHighJumpViolations() {
        this.highJumpViolations = 0;
    }
    
    public int getSpeedViolations() {
        return speedViolations;
    }
    
    public void incrementSpeedViolations() {
        this.speedViolations++;
    }
    
    public void decrementSpeedViolations() {
        this.speedViolations = Math.max(0, this.speedViolations - 1);
    }
    
    public void resetSpeedViolations() {
        this.speedViolations = 0;
    }
    
    public int getAutoClickViolations() {
        return autoClickViolations;
    }
    
    public void incrementAutoClickViolations() {
        this.autoClickViolations++;
    }
    
    public void decrementAutoClickViolations() {
        this.autoClickViolations = Math.max(0, this.autoClickViolations - 1);
    }
    
    public void resetAutoClickViolations() {
        this.autoClickViolations = 0;
    }
    
    public List<Long> getClicks() {
        return clicks;
    }
    
    public void addXRayValue(int value) {
        xrayValues.add(value);
        xrayTimestamps.add(System.currentTimeMillis());
    }
    
    public int getXRayValue(long timeWindow) {
        long currentTime = System.currentTimeMillis();
        int total = 0;
        
        for (int i = 0; i < xrayTimestamps.size(); i++) {
            if (currentTime - xrayTimestamps.get(i) <= timeWindow) {
                total += xrayValues.get(i);
            }
        }
        
        return total;
    }
}
